﻿var PEACON_URL;

// 集成开发环境
if (location.host.indexOf("dev.pajkdc.com") != -1) {
    PEACON_URL = "jktracking.test.jk.cn/wap211/a.gif";
}

    // 本地测试环境
else if (location.host.indexOf("test.pajkdc.com") != -1) {
    PEACON_URL = 'jktracking.test.jk.cn/wap211/a.gif';
}

    // 外网测试环境
else if (location.host.indexOf("test.pajk.cn") != -1) {
    PEACON_URL = 'jktracking.test.jk.cn/wap211/a.gif';
}

    // 预发环境
else if (location.host.indexOf("pre.jk.cn") != -1) {
    PEACON_URL = 'jktracking.jk.cn/wap211/a.gif';
}

    // 正式线上环境
else if (location.host.indexOf("jk.cn") != -1) {
    PEACON_URL = "jktracking.jk.cn/wap211/a.gif";
} else {
    //
}

;
(function (window, document, undefined) {
    if (window.pajkLogger) { //防止重复执行.
        return;
    }
    var utils = {
        jsName: 'pajk_beacon.js',
        defaultVer: 20120104,
        getVersion: function () {
            var jsFileName = this.jsName;
            var rName = new RegExp(jsFileName + "(\\?(.*))?$");
            var jss = document.getElementsByTagName('script');
            for (var i = 0; i < jss.length; i++) {
                var j = jss[i];
                if (j.src && j.src.match(rName)) {
                    var ver = j.src.match(rName)[2];
                    if (ver && (/^[a-zA-Z0-9]+$/).test(ver)) {
                        return ver;
                    }
                }
            }
            return this.defaultVer;
        },
        getCookie: function (sName) {
            var arr = document.cookie.match(new RegExp("(^| )" + sName + "=([^;]*)(;|$)"));
            return (arr != null) ? unescape(arr[2]) : '-';
        },
        setCookie: function (sName, value, exp, path, domain, secure) {
            var expires = new Date;
            exp = typeof exp == 'undefined' ? '' : ';expires=' + new Date(expires.getTime() + (exp * 24 * 60 * 60 * 1000)).toUTCString();
            document.cookie = sName + "=" + value + exp + ((domain == null) ? "" : ("; domain=" + domain)) + ((path == null) ? "" : ("; path=" + path)) + ((secure == true) ? "; secure" : "");
        },
        parseError: function (err) {
            var str = "";
            for (var i in err) {
                str += i + "=" + err[i] + ";";
            }
            return str;
        },
        getRand: function () {
            var _time = new Date,
                getBits = function (val, start, end) {
                    val = val.toString(36).split('');
                    start = start / 4 | 0;
                    end = end / 4 | 0;
                    for (var i = start; i <= end; i++) !val[i] && (val[i] = 0);
                    return val.slice(start, end + 1).join('');
                },
                rand = function (max) {
                    return Math.random() * (max + 1) | 0;
                },
                hnv1a = function (key) {
                    key = key.replace(/./g, function (m) {
                        return m.charCodeAt();
                    }).split('');
                    var p = 16777619,
                        hash = 0x811C9DC5,
                        l = key.length;
                    for (var i = 0; i < l; i++) {
                        hash = (hash ^ key[i]) * p;
                    }
                    hash += hash << 13;
                    hash ^= hash >> 7;
                    hash += hash << 3;
                    hash ^= hash >> 17;
                    hash += hash << 5;
                    hash = hash & 0x7FFFFFFF; //取正.
                    hash = hash.toString(36)
                    hash.length < 6 && (hash += (l % 36).toString(36))
                    return hash;
                },
                info = [
                    screen.width,
                    screen.height,
                    navigator.plugins.length,
                    navigator.javaEnabled(),
                    screen.colorDepth,
                    location.href,
                    navigator.userAgent
                ].join('');
            return function () {
                var s = new Date,
                    t = (+s + 0x92f3973c00).toString(36),
                    m = getBits(rand(0xfff), 0, 7) +
                        getBits(rand(0x1fff), 0, 7) +
                        getBits(rand(0x1fff), 0, 8),
                    c = Math.random() * (251) + 50 | 0, // random from 50 - 300
                    a = [];
                t.length < 9 && (t += (s % 36).toString(36));
                for (; c--;) { //借助不定次数,多次随机，打散客户端，因软硬环境类似，导致产生随机种子的线性规律性，以及重复性.
                    a.push(Math.random());
                }
                return hnv1a(info) + //增加物理维度分流.
                    hnv1a([ //增加用户随机性分流.
                        document.documentElement.offsetWidth,
                        document.documentElement.offsetHeight,
                        history.length,
                        new Date - _time
                    ].join('')) +
                    t +
                    m +
                    hnv1a(a.slice(0, 10).join('')) +
                    hnv1a(a.slice(c - 9).join(''));
            };
        }(),
        getParam: function (data, isSecure) {
            var result = null;
            if (data) {
                if (utils.isString(data) || utils.isNumber(data)) {
                    result = data;
                } else if (utils.isObject(data)) {
                    var str = '';
                    for (var k in data) {
                        if (data[k] != null && data[k] != undefined) {
                            var v = data[k];
                            if (utils.isArray(v)) {
                                v = v.join(",");
                            } else if (utils.isDate(v)) {
                                v = v.getTime();
                            }
                            str += k + '=' + v + '&';
                        }
                    }
                    str = str.substring(0, str.length - 1);
                    result = str;
                } else if (utils.isArray(data)) {
                    if (data.length & data.length > 0) {
                        result = data.join(",");
                    }
                } else {
                    result = data.toString();
                }
            }
            if (!result) {
                result = '-';
            }
            if (isSecure) {
                result = encodeURIComponent(result);
                result = this.base64encode(utils.utf16to8(result));
            }
            return result;
        },
        base64encode: function (input) {
            var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
            var output = "";
            var chr1, chr2, chr3 = "";
            var enc1, enc2, enc3, enc4 = "";
            var i = 0;
            do {
                chr1 = input.charCodeAt(i++);
                chr2 = input.charCodeAt(i++);
                chr3 = input.charCodeAt(i++);
                enc1 = chr1 >> 2;
                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
                enc4 = chr3 & 63;
                if (isNaN(chr2)) {
                    enc3 = enc4 = 64;
                } else if (isNaN(chr3)) {
                    enc4 = 64;
                }
                output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2)
                    + keyStr.charAt(enc3) + keyStr.charAt(enc4);

                chr1 = chr2 = chr3 = "";
                enc1 = enc2 = enc3 = enc4 = "";
            } while (i < input.length);
            return output;
        },
        utf16to8: function (str) {
            var out, i, len, c;
            out = "";
            len = str.length;
            for (i = 0; i < len; i++) {
                c = str.charCodeAt(i);
                if ((c >= 0x0001) && (c <= 0x007F)) {
                    out += str.charAt(i);
                } else if (c > 0x07FF) {
                    out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
                    out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
                    out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
                } else {
                    out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
                    out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
                }
            }
            return out;
        },
        isString: function (str) {
            return (str != null) && (str != undefined) && (typeof str == 'string') && (str.constructor == String);
        },
        isNumber: function (num) {
            return (typeof num == 'number') && (num.constructor == Number);
        },
        isDate: function (d) {
            return d && (typeof d == 'object') && d.constructor == Date;
        },
        isArray: function (arr) {
            return arr && (typeof arr == 'object') && (arr.constructor == Array);
        },
        isObject: function (obj) {
            return obj && (typeof obj == 'object') && (obj.constructor == Object);
        },
        createFlash: function (container, info, params) {
            params = params && params.replace(/"/g, '&quot;');
            var html;
            info.id = info.id || 'pajk_beacon_flash';
            if ('classid' in document.createElement('object')) { //ie only
                // IE下必须有id属性，不然与javascript交互会报错
                html = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" name="' + info.id + '" ' +
                    (info.id ? 'id="' + info.id + '" ' : '') +
                    'width="' + info.width + '" height="' + info.height + '">' +
                    '<param name="allowScriptAccess" value="always" />' +
                    '<param name="quality" value="high" />' +
                    '<param name="wmode" value="window" />' +
                    '<param name="movie" value="' + info.src + '" />' +
                    (params ? '<param name="flashvars" value="' + params + '" />' : '') +
                    '</object>';
            } else {
                html = '<embed style="width:1px;height:1px;" wmode="window" src="' + info.src + '" quality="high" name="' + info.id + '" ' +
                    (info.id ? 'id="' + info.id + '" ' : '') +
                    (params ? 'flashVars="' + params + '" ' : '') +
                    'width="' + info.width + '" height="' + info.height + '" allowScriptAccess="always" ' +
                    'type="application/x-shockwave-flash"/>';
            }
            container.innerHTML = html;
            return container.firstChild;
            //应注意, container必须在DOM Tree中， 否则 先更新innerHTML,后进入DOM Tree, 部分IE8可能flash无法正常显示，并工作.
        }
    },
        _flashContainer,
        _flashObject,
        _flashReady,
        _isFlashReady = true,
        _flashTimer,
        _flashTimeout = 8000,
        _flashKey = 'SNDA_PAJK_BEACON_0',
        _flashURL = '//ipic.staticsdo.com/external/share.swf',
        _fcServer = '//bf.snyu.pajk.com/bf?fn=pajkLogger.__FC__',
        _flashCookie,
        _flashInit,
        _fv = function () { // flash version. 提前检测.用于.决定，是否使用flash 共享对象.
            var list = navigator.plugins;
            if (list && list.length) {
                for (var i = list.length; i--;) {
                    if (/Shockwave Flash/.test(list[i].name)) {
                        return list[i].description.substr(16);
                    }
                }
            } else if (window.ActiveXObject) {
                try {
                    return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version").replace(/^WIN /i, '');
                } catch (e) { }
            }
            return 0;
        }(),
        _refer,
        _request = function () {
            var list = [];
            return function (url) {
                //借助list 保持image 句柄.否则某些浏览器,尤其是ie6,会在页面触发gc时.导致request被abort掉.
                var index = list.push(new Image) - 1;
                /*

                 content length 为0 或 mimeTypes 不是image .则onload会失效。所以此处onload回收，无意义.

                 list[index].onload = function(){

                 list[index] = list[index].onload = null;

                 }



                 */
                list[index].src = url;
            }
        }(),
        _sendTrackLogRequest,
        _trackParams,
        _trackLogTrimStack,
        _cutTrackLog = function () { //执行当权，权重最低的。裁剪参数策略.并使该策略出栈. 如果所有策略已经全部出栈.则返回 false.
            var cutMethod = _trackLogTrimStack.pop();
            cutMethod && cutMethod();
            return !!cutMethod;
        },
        _checkURL = function (url) { //检查trackLog URL 是否超出限制. 如果超出则 返回 false.
            var len = url.length,
                serverLimit = 2048, //上报服务器允许的url长度
                ieLimit = Math.min(2083, serverLimit),
                otherBrowserMinLimit = 65536, //Firefox 65536 , Safari 80000, Opera 190000, Chrome ~= 20000000
                otherLimit = Math.min(serverLimit, otherBrowserMinLimit);
            if (!+'\v1' || window.XDomainRequest) { //ie
                return len <= ieLimit;
            }
            return len <= otherLimit;
        },
        vc = isNaN(vc = +utils.getCookie('beacon_visit_count')) ? 1 : vc + 1;
    utils.setCookie('beacon_visit_count', vc);
    var pajkLogger = {
        uvId: "pajk_beacon_id",
        memId: "pajk_dw_track",
        //beaconUrl : "dwtracking.pajk.com/a.gif",
        //beaconUrl: "dwtracking.jk.cn/b.gif",
        beaconUrl: PEACON_URL,
        errorUrl: PEACON_URL,
        //errorUrl: "dwtracking.jk.cn/error.html",
        clickUrl: PEACON_URL,
        //clickUrl: "dwtracking.jk.cn/click.html",
        pageId: typeof _beacon_pageid != 'undefined' ? _beacon_pageid : utils.getRand(),
        protocol: (document.URL.substring(0, document.URL.indexOf("://"))) + "://",
        tracking: function () {
            //this.beaconLog();
        },
        beaconLog: function () {
            try {
                var _this = this;
                //var fullPath = document.URL.indexOf("://");
                //var path = "{" + utils.getParam(document.URL.substring(fullPath + 2)) + "}";
                _refer = "{" + utils.getParam(this.getRefer()) + "}";
                var userDataObj = {};
                this.ptId = utils.getCookie(this.memId);
                this.cId = utils.getCookie(this.uvId);
                var memCookie = this.ptId;
                var flagCookie = utils.getCookie("b_t_s");
                var subIsNew = flagCookie == '-' || flagCookie.indexOf('s') == -1;
                if (memCookie != '-') {
                    userDataObj.memId = memCookie;
                }
                if (subIsNew) {
                    userDataObj.subIsNew = 1;
                    utils.setCookie("b_t_s", flagCookie == '-' ? 's' : (flagCookie + 's'), 10000, "/");
                } else {
                    userDataObj.subIsNew = 0;
                }
                var userInfo = "{" + utils.getParam(userDataObj) + "}";
                var pageId = this.pageId;
                var title = document.title;
                if (title.length > 50) {
                    title = title.substring(0, 49);
                }
                title = encodeURIComponent(title);
                var charset = document.charset || document.characterSet;
                _trackParams = {
                    pageId: pageId,
                    title: title,
                    charset: charset,
                    sr: window.screen.width + '*' + window.screen.height,
                    url: window.location.href,
                    vc: vc, // visit_count
                    jv: +navigator.javaEnabled(), //java enabled
                    cd: window.screen.colorDepth, // color depth
                    fv: _fv
                };
                //custom_var
                typeof _beacon != 'undefined' && utils.isString(_beacon) && (_trackParams.cv = encodeURIComponent(_beacon));
                //flashCookie
                _trackParams.fc = _flashCookie;
                //裁剪策略入栈操作
                _trackLogTrimStack = [
                    function () { //完全去掉 charset信息.
                        delete _trackParams.charset
                        //window.console && console.log('url过长,去掉charset上报');
                    },
                    function () { //完全去掉 resolution
                        delete _trackParams.sr
                        //window.console && console.log('url过长,去掉sr上报');
                    },
                    function () { //完全去掉 visit_count
                        delete _trackParams.vc
                        //window.console && console.log('url过长,去掉vc上报');
                    },
                    function () { //完全去掉corlor depth
                        delete _trackParams.cd;
                        //window.console && console.log('url过长,去掉cd上报');
                    },
                    function () { //完全去掉java enabled
                        delete _trackParams.jv;
                        //window.console && console.log('url过长,去掉jv上报');
                    },
                    function () { //完全去掉flash version.
                        delete _trackParams.fv;
                        //window.console && console.log('url过长,去掉fv上报');
                    },
                    function () { //完全去掉title
                        delete _trackParams.title;
                        //window.console && console.log('url过长,去掉title上报');
                    },
                    function () { //尝试完全去掉 custom_var
                        delete _trackParams.cv;
                        //window.console && console.log('url过长,去掉cv上报');
                    },
                    function () { //裁剪掉refer的querystring部分.
                        _refer = _refer.split('?')[0];
                        //window.console && console.log('url过长,执行了refer裁切策略.尝试去掉refer的查询字符串部分.处理后refer为:' + _refer);
                    },
                    function () { //裁剪title控制在20个字符以内.
                        var title = decodeURIComponent(_trackParams.title);
                        _trackParams.title = encodeURIComponent(title.substr(0, 19));
                        //window.console && console.log('url过长,执行了title裁切策略.尝试限制其不超过20个字符.处理后title为:' + decodeURIComponent(_trackParams.title));
                    }
                ];
                (_sendTrackLogRequest = function () {
                    var pageParam = "{" + utils.getParam(_trackParams) + "}";
                    var data = {
                        'r': _refer,
                        'a': userInfo,
                        'b': pageParam
                    };
                    /*   window.console && console.log('尝试上报:\n' + [

                     'pageId : ' + _trackParams.pageId,

                     'title : ' + decodeURIComponent(_trackParams.title),

                     'refer : ' + _refer,

                     'cv : ' + decodeURIComponent(_trackParams.cv),

                     'jv : ' + _trackParams.jv,

                     'cd : ' + _trackParams.cd,

                     'vc : ' + _trackParams.vc,

                     'sr : ' + _trackParams.sr,

                     'fc : ' + _trackParams.fc,

                     'charset : ' + _trackParams.charset

                     ].join('\n'));

                     */
                    _this.sendRequest(_this.beaconUrl, data);
                })();
            } catch (err) {
                this.sendError(err);
            }
        },
        getRefer: function () {
            var refer = document.referrer;
            refer == location.href && (refer = ''); //opera 如果没有refer ,则refer为 当前的页面地址.
            try {
                refer = "" == refer ? opener.location : refer;
                refer = "" == refer ? "-" : refer;
            } catch (e) {
                refer = "-";
            }
            return refer;
        },
        clickLog: function (dataObj) {
            try {
                this.sendRequest(this.clickUrl, dataObj);
            } catch (err) {
                this.sendError(err);
            }
        },
        sendError: function (err) {
            var errStr = utils.parseError(err);
            var err_url = this.errorUrl + "?type=send&exception=" + encodeURIComponent(errStr.toString());
            var newImg = new Image();
            newImg.onload = function () {
                newImg = null;
            }
            newImg.src = this.protocol + err_url;
        },
        sendRequest: function (url, param) {
            var base_str = "";
            var userInfo = {};
            var d = new Date();
            param[1] = d.getTime(); //timemillis
            try {
                if (param) {
                    var str = JSON.stringify(param);
                    console.log('%c BEACON' + str, 'background: #222; color: #bada55');
                    base_str = utils.base64encode(utils.utf16to8(str));
                }
                url = this.protocol + url + '?s=' + base_str;
                if (!_checkURL(url)) { //如检测url过长.则尝试使用一个当前，权重最低的裁剪策略.
                    if (_cutTrackLog()) { //如果已经无策略可用.则强制上报.
                        return _sendTrackLogRequest();
                    }
                    //window.console && console.log('所有url裁剪策略,都已处理过,url长度仍然过长.强制上报 : ' + url);
                }
                //window.console && console.log('成功上报 : ' + url);
                //window.console && console.log('url长度为 : ' + url.length);
                _request(url);
            } catch (err) {
                this.sendError(err);
            }
        }
    };
    if (location.protocol == 'http:') {
        // window.console && console.log('.当前页面为http协议,尝试检测用户环境是否支持flash');
        if (false) { //阻止了不必要的flash的监控2014/07/08陶威
            //window.console && console.log('.支持flash插件');
            //_flashCookie , _flashKey, _flashObject, _flashURL, _flashTimeout
            (_flashInit = function () {
                var body = document.body;
                //window.console && console.log('.检测body对象是否可用');
                if (body) {
                    //window.console && console.log('.body对象可用,尝试进一步创建flash对象');
                    _flashReady = function () {
                        //window.console && console.log('.flash开始尝试操作 共享对象');
                        var val, //ie, swf,走缓存，不触发ready回调.
                            js;
                        try {
                            val = _flashObject.get(_flashKey);
                        } catch (e) {
                            //window.console && console.log('.操作flash共享对象,发生异常,尝试直接上报.');
                            _flashCookie = -1;
                            pajkLogger.tracking(); //无论是否取到flashCookie,都直接上报，如果取到,则上报中会出现fc字段.
                            return; //发生异常，直接上报并返回.
                        }
                        if (val) {
                            //window.console && console.log('.flash共享对象值为 : ' + val);
                            _flashCookie = val; //正常获取到用户具有flash cookie,则 weblog.fc = 这个值.
                        } else { //去服务器获取 flashCookie的字串.
                            //window.console && console.log('.flash共享对象值为 : 空');
                            _flashCookie = ''; //发现flash cookie 为空, 则weblog.fc ='' 上报.
                            pajkLogger.__FC__ = function (fc) { //服务器返回flashCookie的约定接口.
                                // window.console && console.log('.已从服务器成功获取同步字串,并尝试写入flash 共享对象,值为 : ' + fc);
                                _flashObject.flush(_flashKey, fc);
                                //window.console && console.log('.共享对象，数据写入 - ' + (_flashObject.get(_flashKey) == fc ? '成功' : '失败'));
                            };
                            js = document.createElement('script');
                            //window.console && console.log('.尝试去服务器端获取同步字串');
                            body.insertBefore(js, body.firstChild);
                            js.src = _fcServer;
                        }
                        //window.console && console.log('.flash共享对象，操作完毕,尝试上报');
                        pajkLogger.tracking(); //无论是否取到flashCookie,都直接上报，如果取到,则上报中会出现fc字段.
                    };
                    _flashContainer = document.createElement('div');
                    body.insertBefore(_flashContainer, body.firstChild);
                    _flashContainer.style.cssText = 'position:absolute;display:block;left:-500px;width:1px;height:1px;';
                    pajkLogger.__FLASHREADY__ = function () { //flashReady
                        if (_isFlashReady) {
                            return;
                        }
                        //window.console && console.log('.flash对象已准备好,并触发了页面回调');
                        _isFlashReady = true;
                        clearTimeout(_flashTimer);
                        if (_flashObject.get && _flashObject.flush) {
                            _flashReady();
                        } else { //setTimeout确保flash暴露的api可用.
                            setTimeout(_flashReady, 100);
                        }
                    };
                    //createFlash.
                    //window.console && console.log('.创建flash对象,等待flash 加载与触发回调');
                    _flashObject = utils.createFlash(_flashContainer, {
                        width: 1,
                        height: 1,
                        src: _flashURL
                    });
                    _flashTimer = setTimeout(function () { //超时上报.
                        if (_isFlashReady) {
                            return;
                        }
                        //window.console && console.log('.flash加载，与回调超时,当前超时时间为: ' + _flashTimeout + 'ms');
                        if (_flashObject && _flashObject.get && _flashObject.flush) {
                            //window.console && console.log('.经检测,虽然已超时,但flash加载已完成.并且外部接口已可用.本次上报将正常操作flash共享对象内容');
                            _isFlashReady = true;
                            _flashReady();
                        } else {
                            //window.console && console.log('.经检测,超时，且flash对象不可用.立刻尝试超时上报');
                            pajkLogger.__FLASHREADY__ = function () {
                                //置空__FLASHREADY__,避免flash后期rady时再次上报.
                            };
                            _flashCookie = -1; //无法确定客户端是否有flash cookie, 则weblog.fc = -1.
                            pajkLogger.tracking();
                        }
                    }, _flashTimeout);
                } else {
                    //window.console && console.log('.body对象不可用,定时器延迟50ms后，尝试再次检测body是否可用');
                    setTimeout(_flashInit, 50);
                }
            })();
        } else {
            //window.console && console.log('.不支持flash,尝试直接上报');
            _flashCookie = 0; //weblog.fc = 0 表示用户浏览器不支持flash,无法使用flash cookie
            pajkLogger.tracking();
        }
    } else {
        //window.console && console.log('.当前页面为https协议, 不使用flash共享对象,尝试直接上报');
        _flashCookie = -2; //weblog.fc = -2 表示为https上报.
        pajkLogger.tracking();
    }
    window.pajkLogger = pajkLogger;
    if (/\.ku6\.com$/.test(location.hostname)) {
        var factor = 5;
        if (window.pajkLogger && window.pajkLogger.pageId && Math.round(Math.random() * 10) == factor) {
            var expiredYY = utils.getCookie("_expireYY");
            if (expiredYY == '-') {
                var url = 'ms.yoyi.com.cn/r/m';
                url = window.pajkLogger.protocol + url + '?s=12&uid=' + window.pajkLogger.pageId;
                _request(url);
                utils.setCookie("_expireYY", 1, 30, "/");
            }
        }
    }
})(window, document);
